package com.usbserial.scale.adapter;

import android.util.Log;

import com.usbserial.core.SerialPort;
import com.usbserial.core.UsbSerialDeviceInfo;
import com.usbserial.exception.UsbSerialException;
import com.usbserial.scale.adapter.aclas.AclasOS2XAdapter;
import com.usbserial.scale.adapter.mettler.MettlerToledoAdapter;

import java.util.ArrayList;
import java.util.List;

/**
 * 电子秤适配器管理器
 * 负责适配器的注册、选择和创建
 *
 * 职责：
 * - 维护已注册的适配器列表
 * - 根据设备信息匹配并创建适配器实例
 * - 提供适配器查询功能
 */
public class ScaleAdapterManager {

    private static final String TAG = "ScaleAdapterManager";

    // 已注册的适配器类列表
    private static final List<Class<? extends ScaleAdapter>> registeredAdapters = new ArrayList<>();

    static {
        // 静态初始化块，在类加载时注册所有适配器
        registerAdapter(AclasOS2XAdapter.class);
        // 注意：MettlerToledoAdapter 与 Aclas 使用相同的 VID/PID
        // 不在此处自动注册，需要手动选择
        // registerAdapter(MettlerToledoAdapter.class);
    }

    /**
     * 注册适配器
     * 允许动态添加新的适配器支持
     *
     * @param adapterClass 适配器类
     */
    public static void registerAdapter(Class<? extends ScaleAdapter> adapterClass) {
        if (adapterClass == null) {
            Log.w(TAG, "Attempted to register null adapter class");
            return;
        }
        if (!registeredAdapters.contains(adapterClass)) {
            registeredAdapters.add(adapterClass);
            Log.d(TAG, "Registered adapter: " + adapterClass.getSimpleName());
        } else {
            Log.w(TAG, "Adapter already registered: " + adapterClass.getSimpleName());
        }
    }

    /**
     * 取消注册适配器
     *
     * @param adapterClass 适配器类
     */
    public static void unregisterAdapter(Class<? extends ScaleAdapter> adapterClass) {
        if (registeredAdapters.remove(adapterClass)) {
            Log.d(TAG, "Unregistered adapter: " + adapterClass.getSimpleName());
        }
    }

    /**
     * 手动创建指定类型的适配器
     * 用于解决多个设备使用相同 VID/PID 的情况
     *
     * @param adapterClass 适配器类
     * @param deviceInfo USB 设备信息
     * @param port 已打开的串口连接
     * @return 适配器实例，如果创建失败则返回 null
     */
    public static ScaleAdapter createAdapterByType(
            Class<? extends ScaleAdapter> adapterClass,
            UsbSerialDeviceInfo deviceInfo,
            SerialPort port) {
        try {
            ScaleAdapter adapter = adapterClass.newInstance();
            Log.i(TAG, "手动创建适配器: " + adapter.getName() +
                  " v" + adapter.getVersion());

            adapter.initialize(port, deviceInfo);
            return adapter;
        } catch (InstantiationException e) {
            Log.e(TAG, "Failed to instantiate adapter: " + adapterClass.getSimpleName(), e);
        } catch (IllegalAccessException e) {
            Log.e(TAG, "Cannot access adapter constructor: " + adapterClass.getSimpleName(), e);
        } catch (UsbSerialException e) {
            Log.e(TAG, "Failed to initialize adapter: " + adapterClass.getSimpleName(), e);
        } catch (Exception e) {
            Log.e(TAG, "Unexpected error creating adapter: " + adapterClass.getSimpleName(), e);
        }
        return null;
    }

    /**
     * 根据设备信息创建适配器（自动匹配）
     * 按注册顺序遍历所有适配器，返回第一个匹配的
     *
     * @param deviceInfo USB 设备信息
     * @param port 已打开的串口连接
     * @return 匹配的适配器实例，如果没有匹配则返回 null
     */
    public static ScaleAdapter createAdapter(UsbSerialDeviceInfo deviceInfo, SerialPort port) {
        if (deviceInfo == null) {
            Log.w(TAG, "Cannot create adapter for null device info");
            return null;
        }

        Log.d(TAG, "Looking for adapter for device: VID=0x" +
              Integer.toHexString(deviceInfo.getVendorId()) +
              " PID=0x" + Integer.toHexString(deviceInfo.getProductId()) +
              " Manufacturer=" + deviceInfo.getManufacturerName() +
              " Product=" + deviceInfo.getProductName());

        // 遍历所有注册的适配器，找到第一个匹配的
        for (Class<? extends ScaleAdapter> adapterClass : registeredAdapters) {
            try {
                // 创建适配器实例
                ScaleAdapter adapter = adapterClass.newInstance();
                ScaleDeviceIdentifier identifier = adapter.getDeviceIdentifier();

                Log.d(TAG, "Checking adapter: " + adapter.getName() + " - " + identifier);

                // 检查设备是否匹配
                if (identifier.matches(deviceInfo)) {
                    Log.i(TAG, "Found matching adapter: " + adapter.getName() +
                          " v" + adapter.getVersion());

                    // 初始化适配器
                    try {
                        adapter.initialize(port, deviceInfo);
                        return adapter;
                    } catch (UsbSerialException e) {
                        Log.e(TAG, "Failed to initialize adapter: " + adapter.getName(), e);
                        // 初始化失败，尝试下一个适配器
                        continue;
                    }
                }
            } catch (InstantiationException e) {
                Log.e(TAG, "Failed to instantiate adapter: " + adapterClass.getSimpleName(), e);
            } catch (IllegalAccessException e) {
                Log.e(TAG, "Cannot access adapter constructor: " + adapterClass.getSimpleName(), e);
            } catch (Exception e) {
                Log.e(TAG, "Unexpected error checking adapter: " + adapterClass.getSimpleName(), e);
            }
        }

        // 没有找到匹配的适配器
        Log.w(TAG, "No matching adapter found for device");
        return null;
    }

    /**
     * 列出所有支持的设备
     *
     * @return 所有已注册适配器支持的设备标识符列表
     */
    public static List<ScaleDeviceIdentifier> listSupportedDevices() {
        List<ScaleDeviceIdentifier> devices = new ArrayList<>();
        for (Class<? extends ScaleAdapter> adapterClass : registeredAdapters) {
            try {
                ScaleAdapter adapter = adapterClass.newInstance();
                devices.add(adapter.getDeviceIdentifier());
            } catch (Exception e) {
                Log.e(TAG, "Failed to get identifier from adapter: " +
                      adapterClass.getSimpleName(), e);
            }
        }
        return devices;
    }

    /**
     * 列出所有已注册的适配器
     *
     * @return 适配器信息列表（名称和版本）
     */
    public static List<String> listRegisteredAdapters() {
        List<String> adapters = new ArrayList<>();
        for (Class<? extends ScaleAdapter> adapterClass : registeredAdapters) {
            try {
                ScaleAdapter adapter = adapterClass.newInstance();
                adapters.add(adapter.getName() + " v" + adapter.getVersion());
            } catch (Exception e) {
                adapters.add(adapterClass.getSimpleName() + " (failed to load)");
            }
        }
        return adapters;
    }

    /**
     * 获取已注册的适配器数量
     *
     * @return 适配器数量
     */
    public static int getAdapterCount() {
        return registeredAdapters.size();
    }

    /**
     * 清空所有已注册的适配器
     * 主要用于测试
     */
    public static void clearAll() {
        registeredAdapters.clear();
        Log.d(TAG, "Cleared all registered adapters");
    }
}
